package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.client.ProductFeignClient;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void addToCart(Long skuId, String userId, Integer skuNum) {
        /*
            1.  判断当前这个skuId 在购物车中是否存在！
            true:
                存在 数量相加
            false:
                不存在 直接插入缓存

             2.  添加有放入购物车价格，实时价格！

             3.  每次添加的时候都是默认选中状态！

             4.  苏宁：展示的时候需要按照添加时间排序，京东：修改时间排序！
         */

 /*       String cartKey = getCartKey(userId);
        CartInfo cartInfoExits = (CartInfo) redisTemplate.opsForHash().get(cartKey, skuId.toString());

        //判断
        if (cartInfoExits != null) {
            //名称
            cartInfoExits.setSkuNum(cartInfoExits.getSkuNum() + skuNum);
            //实时价格
            cartInfoExits.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            //选中状态
            if (cartInfoExits.getIsChecked().intValue() == 0) {
                cartInfoExits.setIsChecked(1);
            }
            //修改时间
            cartInfoExits.setUpdateTime(new Date());

        } else {
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            cartInfoExits = new CartInfo();
            cartInfoExits.setSkuId(skuId);
            cartInfoExits.setCartPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExits.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExits.setSkuNum(skuNum);
            cartInfoExits.setUserId(userId);
            cartInfoExits.setSkuName(skuInfo.getSkuName());
            cartInfoExits.setCreateTime(new Date());
            cartInfoExits.setUpdateTime(new Date());
        }

        //修改后写入缓存
        redisTemplate.opsForHash().put(cartKey, skuId, cartInfoExits);
    }*/
        //  购物车数据存在在缓存：需要获取到购物车数据！ 缓存使用哪种数据类型来存储购物车！ hash hset key field value hget key field
        //  key = user:userId:cart field = skuId  value = cartInfo;
        String cartKey = this.getCartKey(userId);

        //  hget key field
        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());

        //  判断
        if (cartInfoExist != null) {
            //  商品存在
            cartInfoExist.setSkuNum(cartInfoExist.getSkuNum() + skuNum);
            //  赋值实时价格
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            //  选中状态
            if (cartInfoExist.getIsChecked().intValue() == 0) {
                cartInfoExist.setIsChecked(1);
            }
            //  赋值修改时间
            cartInfoExist.setUpdateTime(new Date());

        } else {
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            //  创建一个cartInfo
            cartInfoExist = new CartInfo();
            cartInfoExist.setSkuId(skuId);
            cartInfoExist.setCartPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setSkuNum(skuNum);
            cartInfoExist.setUserId(userId);
            cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());
            cartInfoExist.setSkuName(skuInfo.getSkuName());
            cartInfoExist.setCreateTime(new Date());
            cartInfoExist.setUpdateTime(new Date());

        }
        //  修改完成之后，要写入缓存！
        this.redisTemplate.opsForHash().put(cartKey, skuId.toString(), cartInfoExist);
    }

    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
/*        //声明一个未登录状态的购物车
        List<CartInfo> noLoginCartInfoList = new ArrayList<>();
        //判断
        if (!StringUtils.isEmpty(userTempId)) {
            //获取临时购物车key
            String cartKey = getCartKey(userId);
            noLoginCartInfoList = redisTemplate.boundHashOps(cartKey).values();
        }

        //  判断这个集合是否为空！ 只有一个临时用户Id！
        if (!CollectionUtils.isEmpty(noLoginCartInfoList) && !StringUtils.isEmpty(userId)) {
            //排序
            noLoginCartInfoList.sort((o1, o2) -> {
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            });
            return noLoginCartInfoList;
        }
        //-------------------------------------------------------------------------------登录情况
        if (!StringUtils.isEmpty(userId)) {
            //获取登录购物车key
            String cartKey = getCartKey(userId);
            //  根据key 来获取数据：BoundHashOperations<H, HK, HV> hset key field value;
            BoundHashOperations<String, String, CartInfo> boundHashOperations = redisTemplate.boundHashOps(cartKey);
            //声明一个登录的购物车集合
            List<CartInfo> loginCartInfoList = null;
            //判断 若未登录购物车数据不为空
            if (!CollectionUtils.isEmpty(noLoginCartInfoList)) {
                //遍历未登录购物车集合数据
                //看未登录购物车中是否包含已登录集合数据
                noLoginCartInfoList.stream().forEach(cartInfoNoLogin -> {
                    //登录购物车集合中是否包含skuId
                    if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())) {
                        CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());

                        //设置数量
                        cartInfoLogin.setSkuNum(cartInfoLogin.getSkuNum() + cartInfoNoLogin.getSkuNum());
                        //设置更新时间
                        cartInfoLogin.setUpdateTime(new Date());

                        //判断选中状态
                        if (cartInfoNoLogin.getIsChecked().intValue() == 1 && cartInfoLogin.getIsChecked().intValue() == 0) {
                            cartInfoLogin.setIsChecked(1);
                        }
                        //放入redis
                        boundHashOperations.put(cartInfoLogin.getSkuId().toString(), cartInfoLogin);

                    } else {
                        //未登录 直接放
                        cartInfoNoLogin.setUserId(userId);
                        cartInfoNoLogin.setCreateTime(new Date());
                        cartInfoNoLogin.setUpdateTime(new Date());
                        //放入redis
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(), cartInfoNoLogin);
                    }
                });

            }

            //删除未登录购物车
            redisTemplate.delete(getCartKey(userId));

            //获取合并之后的集合
            loginCartInfoList = boundHashOperations.values();

            //排序
            if (!CollectionUtils.isEmpty(loginCartInfoList)) {
                //排序
                loginCartInfoList.sort((o1, o2) -> {
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
                });
                return loginCartInfoList;
            }
        }
        return new ArrayList<>();
    }*/

        //  声明未登录购物车集合
        List<CartInfo> noLoginCartInfoList = new ArrayList<>();
        //  判断：未登录购物车数据！
        if (!StringUtils.isEmpty(userTempId)) {
            //  查询临时购物车集合数据！
            //  获取临时购物车key
            String cartKey = this.getCartKey(userTempId);
            //  hget key field; 不能！ hvals key
            //  cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
            noLoginCartInfoList = this.redisTemplate.boundHashOps(cartKey).values();
        }

        //  判断这个集合是否为空！ 只有一个临时用户Id！
        if (!CollectionUtils.isEmpty(noLoginCartInfoList) && StringUtils.isEmpty(userId)) {
            //  排序：
            noLoginCartInfoList.sort((o1, o2) -> {
                return DateUtil.truncatedCompareTo(o2.getUpdateTime(), o1.getUpdateTime(), Calendar.SECOND);
            });
            //  返回未登录购物车集合数据！
            return noLoginCartInfoList;
        }

        //  ----------------------------以下是登录情况----------------------------------------------------
         /*
        demo:
            登录：  1
                17  1
                18  1

            未登录： 11111
                17  1
                18  1
                19  2

             合并：
                17  2
                18  2
                19  2
         */


        if (!StringUtils.isEmpty(userId)) {
            //  查询登录购物车集合数据！
            //  获取登录购物车key
            String cartKey = this.getCartKey(userId);

            //  根据key 来获取数据：BoundHashOperations<H, HK, HV> hset key field value;
            BoundHashOperations<String, String, CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);

            //  noLoginCartInfoList 不为空才能合并！
            //  第一种方式双重for 循环！
            //            if (!CollectionUtils.isEmpty(noLoginCartInfoList)){
            //                for (CartInfo cartInfoNoLogin : noLoginCartInfoList) {
            //                    for (CartInfo cartInfoLogin : boundHashOperations.values()) {
            //                        if (cartInfoLogin.getSkuId().intValue()==cartInfoNoLogin.getSkuId().intValue()){
            //                            //  数量相加 ，更新updateTime！ 放入缓存！
            //                        }else {
            //                            //  直接放入缓存！
            //                        }
            //                    }
            //                }
            //            }

            //  声明一个登录的购物车集合数据
            List<CartInfo> LoginCartInfoList = null;
            //  第二种方案： 未登录购物车数据不为空！
            if (!CollectionUtils.isEmpty(noLoginCartInfoList)) {
                //  循环遍历这个未登录购物车集合数据
                //  未登录集合数据中是否包含已登录集合数据！
                noLoginCartInfoList.stream().forEach(cartInfoNoLogin -> {
                    //  hget key filed;
                    //                    CartInfo cartInfo = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                    //                    if(noLoginCartInfoList.contains(cartInfo)){
                    //
                    //                    }
                    //  这个登录购物车集合数据中是否包含skuId
                    if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())) {
                        //  数量相加： 17 ,18
                        CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                        //  设置数量
                        cartInfoLogin.setSkuNum(cartInfoLogin.getSkuNum() + cartInfoNoLogin.getSkuNum());
                        //  设置更新时间
                        cartInfoLogin.setUpdateTime(new Date());

                        //  判断选中状态！
                        if (cartInfoNoLogin.getIsChecked().intValue()==1 && cartInfoLogin.getIsChecked().intValue()==0){
                            cartInfoLogin.setIsChecked(1);
                        }

                        //  放入redis！
                        boundHashOperations.put(cartInfoLogin.getSkuId().toString(), cartInfoLogin);
                    } else {
                        //  未登录：直接放入缓存！ 19
                        cartInfoNoLogin.setUserId(userId);
                        cartInfoNoLogin.setCreateTime(new Date());
                        cartInfoNoLogin.setUpdateTime(new Date());
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    }
                });
            }

            //  合并完成之后，删除未登录购物车：
            this.redisTemplate.delete(this.getCartKey(userTempId));
            //  获取到合并之后的所有数据：
            LoginCartInfoList = boundHashOperations.values();

            //  排序：
            if (!CollectionUtils.isEmpty(LoginCartInfoList)) {
                //  排序：
                LoginCartInfoList.sort((o1,o2)->{
                    return DateUtil.truncatedCompareTo(o2.getUpdateTime(),o1.getUpdateTime(),Calendar.SECOND);
                });
                //  返回未登录购物车集合数据！
                return LoginCartInfoList;
            }

        }

        //  返回数据
        return new ArrayList<>();
    }

    @Override
    public void checkCart(Long skuId, String userId, Integer isChecked) {
        //获取购物车数据
        String cartKey = getCartKey(userId);

        CartInfo cartInfo = (CartInfo) redisTemplate.opsForHash().get(cartKey, userId.toString());
        if (cartInfo != null) {
            cartInfo.setIsChecked(isChecked);
        }
        redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
    }

    @Override
    public void deleteCart(Long skuId, String userId) {
        //获取购物车数据
        String cartKey = getCartKey(userId);

        //删除
        redisTemplate.opsForHash().delete(cartKey,skuId.toString());
    }

    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        String cartKey = getCartKey(userId);

        List<CartInfo> cartInfoList = redisTemplate.opsForHash().values(cartKey);
        //获得购物车集合 拿出选中的商品集合
        List<CartInfo> cartInfoCheckedList  = cartInfoList.stream().filter(cartInfo -> {
          //确认价格
            cartInfo.setSkuPrice(productFeignClient.getSkuPrice(cartInfo.getSkuId()));
            return cartInfo.getIsChecked().intValue() == 1;
        }).collect(Collectors.toList());
        //返回数据集合
        return cartInfoCheckedList ;
    }


    private String getCartKey(String userId) {
        return RedisConst.USER_KEY_PREFIX + userId + RedisConst.USER_CART_KEY_SUFFIX;
    }
}
